#include <stdio.h>
#include <gmp.h>
#include <math.h>
#include <stdlib.h>

int main(){

	mpf_set_default_prec(35000000); //precisao padrao: 35 milhoes de bits (aprox. 10 milhoes em decimal)
	mpf_t a_k, a_k1; //declaracao do a0 e do ak
	mpf_t y_k, y_k1; //declaracao do y0 e do yk
	mpf_t tmp_1, tmp_2, tmp_3, tmp_4, tmp_sup, tmp_inf; //variaveis temporarias usadas no calculo do PI
	mpf_t pi; //variavel que armazenara o valor de PI
	int k;

	FILE *file; //arquivo de saida	

	file = fopen("PI", "w+");               //abre arquivo PI para escrita
	if(file == NULL){
		printf("Erro ao abrir o arquivo\n");
		return 0;
	}
	
	mpf_inits(pi, a_k, y_k, y_k1, a_k1, tmp_1, tmp_2, tmp_3, tmp_4, tmp_sup, tmp_inf, NULL); //comando para inicializar as variaveis

        mpf_sqrt_ui(a_k, 2); 		//
        mpf_mul_ui(a_k, a_k, 4);	// calculo do a0 = 6 - [(4)*(2^1/2)]
        mpf_ui_sub(a_k, 6, a_k);	//

        mpf_sqrt_ui(y_k, 2);		// calculo do y0 = 2^1/2 - 1
        mpf_sub_ui(y_k, y_k, 1);	// 

	
	for(k = 0; k <= 12; k++){
		
		/* Calcula o y_k+1.*/
		mpf_pow_ui(tmp_1, y_k, 4);
		mpf_ui_sub(tmp_2, 1, tmp_1);
		mpf_sqrt(tmp_3, tmp_2);
		mpf_sqrt(tmp_4, tmp_3);
		mpf_ui_sub(tmp_sup, 1, tmp_4);
		mpf_add_ui(tmp_inf, tmp_4, 1);
		mpf_div(y_k1, tmp_sup, tmp_inf);
		/* Fim. */
		
		/* Calcula a_k+1. */
		mpf_add_ui(tmp_1, y_k1, 1);
		mpf_pow_ui(tmp_2, tmp_1, 4);
		mpf_mul(tmp_sup, tmp_2, a_k);
		
		mpf_pow_ui(tmp_2, y_k1, 2);
		mpf_add(tmp_3, tmp_1, tmp_2);
		mpf_mul(tmp_4, y_k1, tmp_3);
		mpf_set_ui(tmp_1, 2);
		mpf_pow_ui(tmp_2, tmp_1, 2*k+3);
		mpf_mul(tmp_inf, tmp_2, tmp_4);
		
		mpf_sub(a_k1, tmp_sup, tmp_inf);
		/* Fim. */
		
		mpf_set(y_k, y_k1);
		mpf_set(a_k, a_k1);
	}
	mpf_ui_div(pi, 1, a_k1); //calcula o inverso do valor de ak1 encontrado, que sera o valor do PI

//	gmp_printf("Pi %.Ff\n", pi);	
	mpf_out_str(file, 10, 0, pi); //imprime o valor do PI no arquivo, com 100000 casas decimais.

	//fecha arquivo e limpa variaveis//
	fclose(file); 	
	file = NULL;	
	mpf_clears(pi, a_k, y_k, y_k1, a_k1, tmp_1, tmp_2, tmp_3, tmp_4, tmp_sup, tmp_inf, NULL);
	//fim//
	
	return 0;

}
